#include "stdafx.h"
#include "hwincom.h"
#include "hwinexception.h"

namespace harlinn
{
    namespace windows
    {

        HWIN_EXPORT bool EnumString::Next( String& theResult )
        {
            InterfaceType* pInterface = GetInterface();
            ULONG numberOfElementsFetched = 0;
            LPOLESTR oleString = nullptr;
            auto hr = pInterface->Next(1, &oleString, &numberOfElementsFetched);
            if(SUCCEEDED(hr))
            {
                theResult = oleString;
                CoTaskMemFree(oleString);
                return true;
            }
            return false;
        }

        HWIN_EXPORT bool EnumString::Next( ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched )
        {
            InterfaceType* pInterface = GetInterface();
            ULONG numberOfElementsFetched = 0;
            auto hr = pInterface->Next(celt, rgelt, &numberOfElementsFetched);
            if(SUCCEEDED(hr))
            {
                if(pceltFetched)
                {
                    *pceltFetched = numberOfElementsFetched;
                }
                return true;
            }
            return false;
        }
        HWIN_EXPORT bool EnumString::Next( ULONG celt, const std::shared_ptr< std::vector<String> >& strings)
        {
            CheckPointerNotNull(strings);
            InterfaceType* pInterface = GetInterface();
            ULONG numberOfElementsFetched = 0;
            LPOLESTR* oleStrings = (LPOLESTR*)alloca(celt*sizeof(LPOLESTR));
            auto hr = pInterface->Next(celt, oleStrings, &numberOfElementsFetched);
            if(SUCCEEDED(hr))
            {
                strings->clear();
                strings->reserve(numberOfElementsFetched);
                for(ULONG i = 0; i < numberOfElementsFetched; i++)
                {
                    LPOLESTR oleString = oleStrings[i];
                    strings->push_back(String(oleString));
                    CoTaskMemFree(oleString);
                }

                return true;
            }
            return false;
        }
        HWIN_EXPORT std::shared_ptr< std::vector<String> > EnumString::All()
        {
            auto result = std::make_shared< std::vector<String> >();
            InterfaceType* pInterface = GetInterface();
            
            LPOLESTR oleStrings[16];
            HRESULT hr = S_OK;
            while(SUCCEEDED(hr))
            {
                ULONG numberOfElementsFetched = 0;
                hr = pInterface->Next(16, oleStrings, &numberOfElementsFetched);
                if(SUCCEEDED(hr))
                {
                    for(ULONG i = 0; i < numberOfElementsFetched; i++)
                    {
                        LPOLESTR oleString = oleStrings[i];
                        result->push_back(String(oleString));
                        CoTaskMemFree(oleString);
                    }
                }
            }
            return result;
        }
        HWIN_EXPORT EnumString& EnumString::Skip( ULONG celt )
        {
            InterfaceType* pInterface = GetInterface( );
            auto hr = pInterface->Skip(celt);
            CheckHRESULT(hr);
            return *this;
        }
        HWIN_EXPORT EnumString& EnumString::Reset( )
        {
            InterfaceType* pInterface = GetInterface( );
            auto hr = pInterface->Reset();
            CheckHRESULT(hr);
            return *this;
        }
        HWIN_EXPORT EnumString EnumString::Clone( )
        {
            InterfaceType* pClone = 0;
            InterfaceType* pInterface = GetInterface( );
            auto hr = pInterface->Clone(&pClone);
            CheckHRESULT(hr);
            EnumString result(pClone);
            return result;
        }

    };
};
